﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Dynamics.BusinessConnectorNet;

namespace PJ.Data
{
    /// <summary>
    /// Dynamics AX server implementation of <see cref="IEntityProvider"> persistence interface. 
    /// </summary>
    /// <typeparam name="TDataInterface">Entity data interface type</typeparam>
    /// <typeparam name="TDataConcreteClass">Entity data concrete class type</typeparam>
    public abstract class EntityAXProvider<TIEntityData> : ObjectAXProvider<TIEntityData>, IEntityProvider<TIEntityData>
        where TIEntityData : class, IEntityData
    {

        protected EntityAXProvider(IEntityCache<TIEntityData> cache) : base(cache)
        {
        }

        protected override void CopyFromContainer(AxaptaContainer container, TIEntityData data)
        {
            base.CopyFromContainer(container, data);
            if (container.Count < 3)
                throw new ArgumentOutOfRangeException("container", container.Count, "should have at least 3 items");
            data.Id = ((string)container.get_Item(3)).Trim();
        }
        IEntityData IEntityProvider.GetById(string id)
        {
            return GetById(id);
        }

        IEntityData IEntityProvider.CachedGetById(string id)
        {
            return CachedGetById(id);
        }

        IEntityData IEntityProvider.FindById(string id)
        {
            return FindById(id);
        }

        IEntityData IEntityProvider.CachedFindById(string id)
        {
            return CachedFindById(id);
        }

        public TIEntityData GetById(string id)
        {
            TIEntityData t = FindById(id);
            if (t == null)
                throw new DataNotFoundException();
            else
                return t;
        }
        public TIEntityData CachedGetById(string id)
        {
            TIEntityData t = CachedFindById(id);
            if (t == null)
                throw new DataNotFoundException();
            else
                return t;
        }
        public TIEntityData FindById(string id)
        {
            if (string.IsNullOrEmpty(id))
                throw new ArgumentNullException("id");
            using (AxaptaContainer container = (AxaptaContainer)CallAXStaticMethod("FindByID", id))
            {
                if (container.Count != 0)
                {
                    TIEntityData data = CreateNewItem(container);
                    if (Cache != null)
                        Cache.Add(data);
                    return data;
                }
                else
                    return null;
            }
        }
        public TIEntityData CachedFindById(string id)
        {
            if (Cache != null)
            {
                TIEntityData i = ((IEntityCache<TIEntityData>)Cache).FindById(id);
                if (i != null)
                    return i;
            }
            return FindById(id);
        }
   }
}
